From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Wed, 30 Oct 2024 00:24:17 +0000 (-0600) Subject: introduce OptionString, (#1352) X-Git-Tag: archive/raspbian/1.10.0+ds-2+rpi1~1^2~12^2^2~29 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=0d8f0f9ec2b89a393ea7d4894c65b6b40ecd7c86;p=gpsbabel.git introduce OptionString, (#1352) * introduce OptionString, a replacement for OptionCString. Formats and filters can be manually converted, with the potential to eliminate c character string usage. OptionCString::get() usages can often use an implicit cast from OptionString instead, although the usage of get() is still valid. * more OptionCString -> OptionString conversion * use custom conversion routines. this introduces OptionString::toInt and OptionString::toDouble, which enforce error checking on conversions. * convert more formats to OptionString * convert gdb to OptionString * convert xcsv, unicsv to OptionString * convert html, text to OptionString * convert ozi to OptionString * convert mtk to OptionString * convert globalsat to OptionString * convert exif to OptionString * convert lowranceusr to OptionString * convert igc to OptionString. note the error checking on timeadj is now done by OptionString::toInt. * prove igc timeadj works with ints. * convert shape to OptionString * convert garmin_gpi to OptionString * consolidate integer/double parse routines. * convert subrip to OptionString * convert garmin_txt to OptionString * enhance OptionString conversions. overloads, as opposed to default parameters, allow tools to find differen usages. improved OptionString error messages with module and argstring information. * enhance argtype ... to indicate integer base and if trailing data is allowed. Use these fields to check and convert integer/doubles in Vecs, fataling on errors. * allow trailng data with parse_distance, parse_speed. and when necessary convert these from ARGTYPE_STRING to ARGTYPE_FLOAT. * fix typo, update refs * convert garmin to OptionString * convert skytraq to OptionString * Introduce OptionInt & OptionDouble. These must be used with ARGTYPE_INT and ARGTYPE_FLOAT. The data is checked and converted in Vecs, and the results may be retrieved by the user. * convert almost all ARGTYPE_INT to OptionInt. * final conversion to OptionInt * mark TODO done. * correct include comments for greps sake. * delete complete TODO comments. * whitespace * use consistent error messags regarding options. i.e. "module(option): " * delete unused Option method type * use ARGTYPE_STRING if trailing data is allowed. The GUI validator used with ARGTYPE_INT and ARGTYPE_FLOAT will reject input with any trailing data. The CLI, including Vecs::assign_option, keys off the Option subclass now, not the ARGTYPE. Note that OptionInt and OptionDouble still allow trailing data. If trailing data is allowed with these classes we just pair these with ARGTYPE_STRING which controls validation in the GUI. * drive arg validation from Option classes. * simplify use of isEmpty delete unused macro delete extraneous file * non member operator== with parameters const QString& not a candidate, parameters are of class OptionString. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c0841ee75..b8a0a9b67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,6 +168,7 @@ set(SUPPORT inifile.cc main.cc mkshort.cc + option.cc parse.cc rgbcolors.cc route.cc diff --git a/arcdist.cc b/arcdist.cc index c72ee1a89..cd0349a2a 100644 --- a/arcdist.cc +++ b/arcdist.cc @@ -112,7 +112,7 @@ void ArcDistanceFilter::process() QString line; gpsbabel::TextStream stream; - stream.open(arcfileopt.get(), QIODevice::ReadOnly, MYNAME); + stream.open(arcfileopt, QIODevice::ReadOnly, MYNAME); auto* arcpt1 = new Waypoint; auto* arcpt2 = new Waypoint; diff --git a/arcdist.h b/arcdist.h index 47526788d..717b6efca 100644 --- a/arcdist.h +++ b/arcdist.h @@ -28,7 +28,7 @@ #include "defs.h" // for ARG_NOMINMAX, ARGTYPE_BOOL, Waypoint (ptr only) #include "filter.h" // for Filter -#include "option.h" // for OptionBool, OptionCString +#include "option.h" // for OptionBool, OptionString #if FILTERS_ENABLED @@ -61,8 +61,8 @@ private: /* Data Members */ double pos_dist{}; - OptionCString distopt; - OptionCString arcfileopt; + OptionDouble distopt; + OptionString arcfileopt; OptionBool rteopt; OptionBool trkopt; OptionBool exclopt; @@ -84,7 +84,7 @@ private: }, { "distance", &distopt, "Maximum distance from arc", - nullptr, ARGTYPE_FLOAT | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr + nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr }, { "exclude", &exclopt, "Exclude points close to the arc", nullptr, diff --git a/bend.cc b/bend.cc index 09325673f..4f7abc2cb 100644 --- a/bend.cc +++ b/bend.cc @@ -21,7 +21,7 @@ */ #include // macos wants abs from here! -#include // for strtod, abs +#include // for abs #include // for as_const #include // for QString @@ -41,12 +41,12 @@ void BendFilter::init() { maxDist = 0.0; if (distopt) { - maxDist = strtod(distopt, nullptr); + maxDist = distopt.get_result(); } minAngle = 0.0; if (minangleopt) { - minAngle = strtod(minangleopt, nullptr); + minAngle = minangleopt.get_result(); } route_backup(&routes_orig); diff --git a/bend.h b/bend.h index 73cf803e8..fd7b101d5 100644 --- a/bend.h +++ b/bend.h @@ -29,7 +29,7 @@ #include "defs.h" // for route_head (ptr only), ARGTYPE_FLOAT, ARG_NOMINMAX #include "filter.h" // for Filter -#include "option.h" // for OptionCString +#include "option.h" // for OptionString #if FILTERS_ENABLED @@ -45,8 +45,8 @@ public: void deinit() override; private: - OptionCString distopt; - OptionCString minangleopt; + OptionDouble distopt; + OptionDouble minangleopt; double maxDist{}; double minAngle{}; diff --git a/defs.h b/defs.h index ac8c54382..34baa610f 100644 --- a/defs.h +++ b/defs.h @@ -866,8 +866,18 @@ extern posn_status tracking_status; * for "groups" of exactly one option. */ #define ARGTYPE_BEGIN_REQ 0x04000000U #define ARGTYPE_END_REQ 0x02000000U +/* For integer conversions specify the base to allow strict error checking and + * proper conversion in Vecs */ +#define ARGTYPE_BASE_10 0x00000000U +#define ARGTYPE_BASE_AUTO 0x00100000U +#define ARGTYPE_BASE_16 0x00200000U + +/* For integer and double conversions is trailing data allowed? + * This allows strict error checking in Vecs */ +#define ARGTYPE_ALLOW_TRAILING_DATA 0x00400000U #define ARGTYPE_TYPEMASK 0x00000fffU +#define ARGTYPE_BASEMASK 0x00300000U #define ARGTYPE_FLAGMASK 0xfffff000U #define ARG_NOMINMAX nullptr, nullptr @@ -1025,13 +1035,13 @@ int xstrtoi(const char* str, char** str_end, int base); /* * From parse.c */ +int parse_integer(const QString& str, const QString& id, bool* ok = nullptr, QString* end = nullptr, int base = 10); +double parse_double(const QString& str, const QString& id, bool* ok = nullptr, QString* end = nullptr); int parse_coordinates(const char* str, int datum, grid_type grid, double* latitude, double* longitude, const char* module); int parse_coordinates(const QString& str, int datum, grid_type grid, double* latitude, double* longitude, const char* module); -int parse_distance(const char* str, double* val, double scale, const char* module); int parse_distance(const QString& str, double* val, double scale, const char* module); -int parse_speed(const char* str, double* val, double scale, const char* module); int parse_speed(const QString& str, double* val, double scale, const char* module); /* diff --git a/discard.cc b/discard.cc index 34ea92258..39a7960e6 100644 --- a/discard.cc +++ b/discard.cc @@ -24,9 +24,7 @@ #include // for QDebug #include // for QRegularExpression, QRegularExpression::CaseInsensitiveOption, QRegularExpressionMatch -#include // for strtod - -#include "defs.h" // for Waypoint, fatal, route_head (ptr only), xstrtoi, del_marked_wpts, route_del_marked_wpts, route_disp_all, track_del_marked_wpts, track_disp_all, waypt_disp_all, fix_none, fix_unknown +#include "defs.h" // for Waypoint, fatal, route_head (ptr only), del_marked_wpts, route_del_marked_wpts, route_disp_all, track_del_marked_wpts, track_disp_all, waypt_disp_all, fix_none, fix_unknown #include "src/core/logging.h" // for FatalMsg @@ -131,51 +129,51 @@ QRegularExpression DiscardFilter::generateRegExp(const QString& glob_pattern) void DiscardFilter::init() { if (hdopopt) { - hdopf = strtod(hdopopt, nullptr); + hdopf = hdopopt.get_result(); } else { hdopf = -1.0; } if (vdopopt) { - vdopf = strtod(vdopopt, nullptr); + vdopf = vdopopt.get_result(); } else { vdopf = -1.0; } if (satopt) { - satpf = xstrtoi(satopt, nullptr, 10); + satpf = satopt.get_result(); } else { satpf = -1; } if (eleminopt) { - eleminpf = xstrtoi(eleminopt, nullptr, 10); + eleminpf = eleminopt.get_result(); } if (elemaxopt) { - elemaxpf = xstrtoi(elemaxopt, nullptr, 10); + elemaxpf = elemaxopt.get_result(); } if (nameopt) { - name_regex = generateRegExp(nameopt.get()); + name_regex = generateRegExp(nameopt); if (!name_regex.isValid()) { fatal(FatalMsg() << "discard: matchname option is an invalid expression."); } } if (descopt) { - desc_regex = generateRegExp(descopt.get()); + desc_regex = generateRegExp(descopt); if (!desc_regex.isValid()) { fatal(FatalMsg() << "discard: matchdesc option is an invalid expression."); } } if (cmtopt) { - cmt_regex = generateRegExp(cmtopt.get()); + cmt_regex = generateRegExp(cmtopt); if (!cmt_regex.isValid()) { fatal(FatalMsg() << "discard: matchcmt option is an invalid expression."); } } if (iconopt) { - icon_regex = generateRegExp(iconopt.get()); + icon_regex = generateRegExp(iconopt); if (!icon_regex.isValid()) { fatal(FatalMsg() << "discard: matchicon option is an invalid expression."); } diff --git a/discard.h b/discard.h index 1325d2600..73c82bebc 100644 --- a/discard.h +++ b/discard.h @@ -29,7 +29,7 @@ #include "defs.h" // for arglist_t, ARG_NOMINMAX, ARGTYPE_BEGIN_REQ, ARGTYPE_STRING, ARGTYPE_BOOL, ARGTYPE_INT, ARGTYPE_FLOAT, route_head, ARGTYPE_END_REQ, Waypoint, gpsdata_type #include "filter.h" // for Filter -#include "option.h" // for OptionCString, OptionBool +#include "option.h" // for OptionString, OptionBool #if FILTERS_ENABLED class DiscardFilter:public Filter @@ -50,21 +50,21 @@ private: /* Data Members */ - OptionCString hdopopt; - OptionCString vdopopt; + OptionDouble hdopopt; + OptionDouble vdopopt; OptionBool andopt; - OptionCString satopt; + OptionInt satopt; OptionBool fixnoneopt; OptionBool fixunknownopt; - OptionCString eleminopt; - OptionCString elemaxopt; - OptionCString nameopt; + OptionInt eleminopt; + OptionInt elemaxopt; + OptionString nameopt; QRegularExpression name_regex; - OptionCString descopt; + OptionString descopt; QRegularExpression desc_regex; - OptionCString cmtopt; + OptionString cmtopt; QRegularExpression cmt_regex; - OptionCString iconopt; + OptionString iconopt; QRegularExpression icon_regex; double hdopf{}; @@ -88,7 +88,7 @@ private: }, { "sat", &satopt, "Minimum sats to keep points", - "-1.0", ARGTYPE_BEGIN_REQ | ARGTYPE_INT, ARG_NOMINMAX, nullptr + "-1", ARGTYPE_BEGIN_REQ | ARGTYPE_INT, ARG_NOMINMAX, nullptr }, { "fixnone", &fixnoneopt, "Suppress points without fix", diff --git a/exif.cc b/exif.cc index 4f6ec2c29..e0bfbfec3 100644 --- a/exif.cc +++ b/exif.cc @@ -722,7 +722,7 @@ ExifFormat::exif_get_exif_time(ExifApp* app) const } if (offset_tag || opt_offsettime) { - QByteArray time_tag = opt_offsettime? QByteArray(opt_offsettime) : exif_read_str(offset_tag); + QString time_tag = opt_offsettime? opt_offsettime : QString(exif_read_str(offset_tag)); // string should be +HH:MM or -HH:MM static const QRegularExpression re(R"(^([+-])(\d{2}):(\d{2})$)"); assert(re.isValid()); @@ -739,7 +739,7 @@ ExifFormat::exif_get_exif_time(ExifApp* app) const } else if (opt_offsettime) { // Only warn for user supplied offsets. // Offset tags may indicate the offset was unknown, e.g. " : ". - warning(MYNAME ": OffsetTime is expected to be +HH:MM or -HH:MM, but was %s.\n", time_tag.constData()); + warning(MYNAME ": OffsetTime is expected to be +HH:MM or -HH:MM, but was %s.\n", qPrintable(time_tag)); } } @@ -1178,7 +1178,7 @@ ExifFormat::exif_find_wpt_by_name(const Waypoint* wpt) { if (exif_wpt_ref != nullptr) { return; - } else if ((wpt->shortname != nullptr) && (case_ignore_strcmp(wpt->shortname, opt_name.get()) == 0)) { + } else if ((wpt->shortname != nullptr) && (case_ignore_strcmp(wpt->shortname, opt_name) == 0)) { exif_wpt_ref = wpt; } } @@ -1530,7 +1530,7 @@ ExifFormat::write() track_disp_all(nullptr, nullptr, exif_find_wpt_by_name_lambda); } if (exif_wpt_ref == nullptr) { - warning(MYNAME ": No matching point with name \"%s\" found.\n", qPrintable(opt_name.get())); + warning(MYNAME ": No matching point with name \"%s\" found.\n", qPrintable(opt_name)); } } else { auto exif_find_wpt_by_time_lambda = [this](const Waypoint* waypointp)->void { @@ -1540,7 +1540,7 @@ ExifFormat::write() route_disp_all(nullptr, nullptr, exif_find_wpt_by_time_lambda); waypt_disp_all(exif_find_wpt_by_time_lambda); - qint64 frame = xstrtoi(opt_frame, nullptr, 10); + qint64 frame = opt_frame.get_result(); if (exif_wpt_ref == nullptr) { warning(MYNAME ": No point with a valid timestamp found.\n"); diff --git a/exif.h b/exif.h index e6ac7409d..050acfb4c 100644 --- a/exif.h +++ b/exif.h @@ -50,7 +50,7 @@ #include "defs.h" // for arglist_t, ff_cap, Waypoint, ARG_NOMINMAX, ARGTYPE_BOOL, ff_cap_none, ARGTYPE_INT, ARGTYPE_STRING, ff_cap_read, ff_cap_write, ff_type, ff_type_file #include "format.h" // for Format #include "gbfile.h" // for gbfile, gbsize_t -#include "option.h" // for OptionCString, OptionBool +#include "option.h" // for OptionString, OptionBool class ExifFormat : public Format @@ -205,9 +205,9 @@ private: OptionBool opt_filename; OptionBool opt_overwrite; - OptionCString opt_frame; - OptionCString opt_name; - OptionCString opt_offsettime; + OptionInt opt_frame; + OptionString opt_name; + OptionString opt_offsettime; QVector exif_args = { { "filename", &opt_filename, "Set waypoint name to source filename", "Y", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, diff --git a/garmin.cc b/garmin.cc index fffc175ca..1f686f67a 100644 --- a/garmin.cc +++ b/garmin.cc @@ -25,14 +25,12 @@ #include // for atan2, modf, sqrt #include // for fprintf, fflush, snprintf, snprintf #include // for int32_t -#include // for strtol #include // for memcpy, strlen, strncpy, strchr #include // for time_t #include // for as_const #include // for QByteArray #include // for QChar -#include // for QList<>::const_iterator #include // for QString #include // for QTextCodec #include // for CaseInsensitive @@ -80,7 +78,7 @@ void GarminFormat::rw_init(const QString& fname) { receiver_must_upper = true; - const char* receiver_charset = "US-ASCII"; + QByteArray receiver_charset = "US-ASCII"; /* Technically, even this is a little loose as spaces aren't allowed */ const char* valid_waypt_chars = MILITANT_VALID_WAYPT_CHARS " "; @@ -102,12 +100,11 @@ GarminFormat::rw_init(const QString& fname) return; } - if (categorybitsopt) { - categorybits = strtol(categorybitsopt, nullptr, 0); - } + category = categoryopt? (1 << (categoryopt.get_result() - 1)) : 0; + categorybits = categorybitsopt? categorybitsopt.get_result() : 0; if (baudopt) { - baud = strtol(baudopt, nullptr, 0); + baud = baudopt.get_result(); switch (baud) { case 9600: case 19200: @@ -258,7 +255,7 @@ GarminFormat::rw_init(const QString& fname) * If the user provided a short_length, override the calculated value. */ if (snlen) { - mkshort_handle->set_length(xstrtoi(snlen, nullptr, 10)); + mkshort_handle->set_length(snlen.get_result()); } else { mkshort_handle->set_length(receiver_short_length); } @@ -287,13 +284,13 @@ GarminFormat::rw_init(const QString& fname) * However, this is still used for garmin_fs_garmin_after_read, * garmin_fs_garmin_before_write. */ - if (opt_codec != nullptr) { + if (opt_codec) { // override expected codec with user supplied choice. - receiver_charset = opt_codec; + receiver_charset = opt_codec.get().toUtf8(); } codec = get_codec(receiver_charset); if (global_opts.verbose_status) { - fprintf(stdout, "receiver charset detected as %s.\r\n", receiver_charset); + fprintf(stdout, "receiver charset detected as %s.\r\n", receiver_charset.constData()); } valid_chars = valid_waypt_chars; @@ -849,7 +846,7 @@ GarminFormat::waypoint_prepare() tx_waylist[i]->lat = wpt->latitude; if (deficon) { - icon = gt_find_icon_number_from_desc(deficon.get(), PCX); + icon = gt_find_icon_number_from_desc(deficon, PCX); } else { if (!wpt->gc_data->get_icon().isEmpty()) { icon = gt_find_icon_number_from_desc(wpt->gc_data->get_icon(), PCX); @@ -877,7 +874,7 @@ GarminFormat::waypoint_prepare() tx_waylist[i]->time_populated = 1; } if (category) { - tx_waylist[i]->category = 1 << (xstrtoi(category, nullptr, 10) - 1); + tx_waylist[i]->category = category; } if (categorybits) { tx_waylist[i]->category = categorybits; diff --git a/garmin.h b/garmin.h index a4f27aef5..0be8a5ff1 100644 --- a/garmin.h +++ b/garmin.h @@ -34,7 +34,7 @@ #include "jeeps/gpsdevice.h" // for gpsdevh #include "jeeps/gpssend.h" // for GPS_PWay, GPS_SWay, GPS_PTrack, GPS_PPvt_Data, GPS_SLap #include "mkshort.h" // for MakeShort -#include "option.h" // for OptionCString, OptionBool +#include "option.h" // for OptionString, OptionBool class GarminFormat : public Format @@ -124,14 +124,15 @@ private: OptionBool poweroff; OptionBool eraset; OptionBool resettime; - OptionCString snlen; + OptionInt snlen; OptionBool snwhiteopt; - OptionCString deficon; - OptionCString category; - OptionCString categorybitsopt; - OptionCString baudopt; - OptionCString opt_codec; + OptionString deficon; + OptionInt categoryopt; + OptionInt categorybitsopt; + OptionInt baudopt; + OptionString opt_codec; int baud = 0; + int category{}; int categorybits{}; bool receiver_must_upper = true; QTextCodec* codec{nullptr}; @@ -165,12 +166,12 @@ private: nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr }, { - "category", &category, "Category number to use for written waypoints", + "category", &categoryopt, "Category number to use for written waypoints", nullptr, ARGTYPE_INT, "1", "16", nullptr }, { "bitscategory", &categorybitsopt, "Bitmap of categories", - nullptr, ARGTYPE_INT, "1", "65535", nullptr + nullptr, ARGTYPE_BASE_AUTO | ARGTYPE_INT, "1", "65535", nullptr }, { "baud", &baudopt, "Speed in bits per second of serial port (baud=9600)", diff --git a/garmin_gpi.cc b/garmin_gpi.cc index 8cfd23653..00b79e304 100644 --- a/garmin_gpi.cc +++ b/garmin_gpi.cc @@ -126,9 +126,9 @@ GarminGPIFormat::gpi_read_string(const char* field) const if (res1.strlen + 4 + res2.strlen + 4 != l0) { fatal(MYNAME ": Error out of sync (wrong size %d/%d/%d) on field '%s'!", l0, res1.strlen, res2.strlen, field); } - if (opt_lang && (opt_lang == res1.lc)) { + if (opt_lang && (opt_lang.get().toUtf8() == res1.lc)) { string = res1.str; - } else if (opt_lang && (opt_lang == res2.lc)) { + } else if (opt_lang && (opt_lang.get().toUtf8() == res2.lc)) { string = res2.str; } else { fatal(MYNAME ": Must select language code, %s and %s found.\n", res1.lc.constData(), res2.lc.constData()); @@ -729,11 +729,11 @@ GarminGPIFormat::wdata_compute_size(writer_data_t* data) const #if 0 wpt->shortname.truncate(pidx); #endif - } else if ((opt_speed) && (!wpt->speed_has_value())) { + } else if (opt_speed && (!wpt->speed_has_value())) { wpt->set_speed(defspeed); } - if ((opt_proximity) && (!wpt->proximity_has_value())) { + if (opt_proximity && (!wpt->proximity_has_value())) { wpt->set_proximity(defproximity); } @@ -976,11 +976,11 @@ skip_empty_block: } void -GarminGPIFormat::write_category(const char* /*unused*/, const unsigned char* image, const int image_sz) const +GarminGPIFormat::write_category(const QString& /*unused*/, const unsigned char* image, const int image_sz) const { int sz = wdata_compute_size(wdata); sz += 8; /* string header */ - sz += str_from_unicode(opt_cat.get()).size(); + sz += str_from_unicode(opt_cat).size(); gbfputint32(0x80009, fout); if ((! opt_hide_bitmap) && image_sz) { @@ -989,7 +989,7 @@ GarminGPIFormat::write_category(const char* /*unused*/, const unsigned char* ima gbfputint32(sz, fout); } gbfputint32(sz, fout); - write_string(str_from_unicode(opt_cat.get()), 1); + write_string(str_from_unicode(opt_cat), 1); wdata_write(wdata); @@ -1052,7 +1052,7 @@ GarminGPIFormat::enum_waypt_cb(const Waypoint* ref) const } void -GarminGPIFormat::load_bitmap_from_file(const char* fname, const unsigned char** data, int* data_sz) +GarminGPIFormat::load_bitmap_from_file(const QString& fname, const unsigned char** data, int* data_sz) { int i; int sz; @@ -1207,6 +1207,19 @@ GarminGPIFormat::load_bitmap_from_file(const char* fname, const unsigned char** gbfclose(f); } +char GarminGPIFormat::parse_units(const QString& str) +{ + char result; + if (str.startsWith('m', Qt::CaseInsensitive)) { + result = 'm'; + } else if (str.startsWith('s', Qt::CaseInsensitive)) { + result = 's'; + } else { + fatal(MYNAME ": Unknown units parameter (%s).\n", qPrintable(str)); + } + return result; +} + /******************************************************************************* * %%% global callbacks called by gpsbabel main process %%% * *******************************************************************************/ @@ -1228,10 +1241,7 @@ GarminGPIFormat::rd_init(const QString& fname) fatal(MYNAME ": Unsupported code page (%d). File is likely encrypted.\n", codepage); } - units = tolower(opt_units[0]); - if ((units != 'm') && (units != 's')) { - fatal(MYNAME ": Unknown units parameter (%c).\n", opt_units[0]); - } + units = parse_units(opt_units); } void @@ -1263,28 +1273,25 @@ GarminGPIFormat::wr_init(const QString& fname) codepage = 0; for (int i = 1250; i <= 1257; i++) { - if (QStringLiteral("windows-%1").arg(i).compare(QString(opt_writecodec), Qt::CaseInsensitive) == 0) { + if (QStringLiteral("windows-%1").arg(i).compare(opt_writecodec, Qt::CaseInsensitive) == 0) { codepage = i; break; } } if (! codepage) { - if (QString("utf8").compare(QString(opt_writecodec), Qt::CaseInsensitive) == 0) { + if (QStringLiteral("utf8").compare(opt_writecodec, Qt::CaseInsensitive) == 0) { codepage = 65001; } } if (! codepage) { - warning(MYNAME ": Unsupported character set (%s)!\n", qPrintable(opt_writecodec.get())); + warning(MYNAME ": Unsupported character set (%s)!\n", qPrintable(opt_writecodec)); fatal(MYNAME ": Valid values are windows-1250 to windows-1257 and utf8.\n"); } - codec = get_codec(opt_writecodec.getba()); + codec = get_codec(opt_writecodec.get().toUtf8()); - units = tolower(opt_units[0]); - if ((units != 'm') && (units != 's')) { - fatal(MYNAME ": Unknown units parameter (%c).\n", opt_units[0]); - } + units = parse_units(opt_units); alerts = (opt_alerts) ? 1 : 0; @@ -1327,8 +1334,8 @@ GarminGPIFormat::wr_deinit() short_h = nullptr; gbfclose(fout); - if ((opt_sleep) && !gpsbabel_testmode()) { /* don't sleep during 'testo' */ - int sleep = xstrtoi(opt_sleep, nullptr, 10); + if (opt_sleep && !gpsbabel_testmode()) { /* don't sleep during 'testo' */ + int sleep = opt_sleep.get_result(); if (sleep < 1) { sleep = 1; } @@ -1359,14 +1366,14 @@ GarminGPIFormat::write() const unsigned char* image; int image_sz; - if (strlen(opt_cat) == 0) { + if (opt_cat.isEmpty()) { fatal(MYNAME ": Can't write empty category!\n"); } if (opt_hide_bitmap) { image = nullptr; image_sz = 0; - } else if (opt_bitmap && *opt_bitmap) { + } else if (!opt_bitmap.isEmpty()) { load_bitmap_from_file(opt_bitmap, &image, &image_sz); } else { image = gpi_bitmap; /* embedded GPSBabel icon in gpi format */ diff --git a/garmin_gpi.h b/garmin_gpi.h index 0efbf81b7..8b380c836 100644 --- a/garmin_gpi.h +++ b/garmin_gpi.h @@ -60,7 +60,7 @@ #include "garmin_fs.h" // for garmin_fs_t #include "gbfile.h" // for gbfile #include "mkshort.h" // for MakeShort -#include "option.h" // for OptionCString, OptionBool +#include "option.h" // for OptionString, OptionBool class GarminGPIFormat : public Format @@ -299,29 +299,30 @@ private: void wdata_check(writer_data_t* data) const; int wdata_compute_size(writer_data_t* data) const; void wdata_write(const writer_data_t* data) const; - void write_category(const char* unused, const unsigned char* image, int image_sz) const; + void write_category(const QString& unused, const unsigned char* image, int image_sz) const; void write_header() const; void enum_waypt_cb(const Waypoint* ref) const; - static void load_bitmap_from_file(const char* fname, const unsigned char** data, int* data_sz); + static void load_bitmap_from_file(const QString& fname, const unsigned char** data, int* data_sz); + static char parse_units(const QString& str); QByteArray str_from_unicode(const QString& qstr) const {return codec->fromUnicode(qstr);} QString str_to_unicode(const QByteArray& cstr) const {return codec->toUnicode(cstr);} /* Data Members */ - OptionCString opt_cat; + OptionString opt_cat; OptionBool opt_pos; OptionBool opt_notes; OptionBool opt_hide_bitmap; OptionBool opt_descr; - OptionCString opt_bitmap; + OptionString opt_bitmap; OptionBool opt_unique; OptionBool opt_alerts; - OptionCString opt_units; - OptionCString opt_speed; - OptionCString opt_proximity; - OptionCString opt_sleep; - OptionCString opt_lang; - OptionCString opt_writecodec; + OptionString opt_units; + OptionDouble opt_speed; + OptionDouble opt_proximity; + OptionInt opt_sleep; + OptionString opt_lang; + OptionString opt_writecodec; double defspeed{}, defproximity{}; int alerts{}; @@ -356,7 +357,7 @@ private: }, { "proximity", &opt_proximity, "Default proximity", - nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr + nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING, ARG_NOMINMAX, nullptr }, { "sleep", &opt_sleep, "After output job done sleep n second(s)", @@ -364,7 +365,7 @@ private: }, { "speed", &opt_speed, "Default speed", - nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr + nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_STRING, ARG_NOMINMAX, nullptr }, { "unique", &opt_unique, "Create unique waypoint names (default = yes)", diff --git a/garmin_txt.cc b/garmin_txt.cc index e52a68198..e9a7bfdc9 100644 --- a/garmin_txt.cc +++ b/garmin_txt.cc @@ -79,24 +79,15 @@ bool GarminTxtFormat::is_valid_alt(double alt) /* helpers */ -const char* -GarminTxtFormat::get_option_val(const char* option, const char* def) -{ - const char* c = (option != nullptr) ? option : def; - return c; -} - void GarminTxtFormat::init_date_and_time_format() { // This is old, and weird, code.. date_time_format is a global that's // explicitly malloced and freed elsewhere. This isn't very C++ at all, // but this format is on its deathbead for deprecation. - const char* d = get_option_val(opt_date_format, kDefaultDateFormat); - QString d1 = convert_human_date_format(d); + QString d1 = convert_human_date_format(opt_date_format); - const char* t = get_option_val(opt_time_format, kDefaultTimeFormat); - QString t1 = convert_human_time_format(t); + QString t1 = convert_human_time_format(opt_time_format); date_time_format = QStringLiteral("%1 %2").arg(d1, t1); } @@ -625,13 +616,8 @@ GarminTxtFormat::track_disp_wpt_cb(const Waypoint* wpt) void GarminTxtFormat::garmin_txt_utc_option() { - if (opt_utc != nullptr) { - if (case_ignore_strcmp(opt_utc.get(), "utc") == 0) { - utc_offs = 0; - } else { - utc_offs = xstrtoi(opt_utc, nullptr, 10); - } - utc_offs *= (60 * 60); + if (opt_utc) { + utc_offs = opt_utc.get_result() * 60 * 60; gtxt_flags.utc = 1; } } @@ -652,30 +638,27 @@ GarminTxtFormat::wr_init(const QString& fname) fout = new gpsbabel::TextStream; fout->open(fname, QIODevice::WriteOnly, MYNAME, "windows-1252"); - gtxt_flags.metric = (toupper(*get_option_val(opt_dist, "m")) == 'M'); - gtxt_flags.celsius = (toupper(*get_option_val(opt_temp, "c")) == 'C'); + gtxt_flags.metric = opt_dist.get().startsWith("m", Qt::CaseInsensitive); + gtxt_flags.celsius = opt_temp.get().startsWith("c", Qt::CaseInsensitive); init_date_and_time_format(); if (opt_precision) { - precision = xstrtoi(opt_precision, nullptr, 10); + precision = opt_precision.get_result(); if (precision < 0) { - fatal(MYNAME ": Invalid precision (%s)!", qPrintable(opt_precision.get())); + fatal(MYNAME ": Invalid precision (%s)!", qPrintable(opt_precision)); } } - QString datum_str = get_option_val(opt_datum, nullptr); - QString grid_str = get_option_val(opt_grid, nullptr); - grid_index = grid_lat_lon_dmm; - if (!grid_str.isEmpty()) { + if (!opt_grid.isEmpty()) { bool ok; - if (int i = grid_str.toInt(&ok); ok) { + if (int i = opt_grid.toInt(&ok); ok) { grid_index = (grid_type) i; if ((grid_index < GRID_INDEX_MIN) || (grid_index > GRID_INDEX_MAX)) - fatal(MYNAME ": Grid index out of range (%d..%d)!", + fatal(MYNAME ": Grid index out of range (%d..%d)!\n", (int)GRID_INDEX_MIN, (int)GRID_INDEX_MAX); } else { - grid_index = gt_lookup_grid_type(grid_str, MYNAME); + grid_index = gt_lookup_grid_type(opt_grid, MYNAME); } } @@ -687,7 +670,7 @@ GarminTxtFormat::wr_init(const QString& fname) datum_index = kDatumWGS84; break; default: - datum_index = gt_lookup_datum_index(datum_str, MYNAME); + datum_index = gt_lookup_datum_index(opt_datum, MYNAME); } garmin_txt_utc_option(); diff --git a/garmin_txt.h b/garmin_txt.h index 9af5aa442..969255d75 100644 --- a/garmin_txt.h +++ b/garmin_txt.h @@ -36,7 +36,7 @@ #include "defs.h" #include "format.h" // for Format -#include "option.h" // for OptionCString +#include "option.h" // for OptionString #include "src/core/textstream.h" // for TextStream @@ -69,8 +69,6 @@ private: /* Constants */ static constexpr double kGarminUnknownAlt = 1.0e25; - static constexpr char kDefaultDateFormat[] = "dd/mm/yyyy"; - static constexpr char kDefaultTimeFormat[] = "HH:mm:ss"; static const QVector headers; @@ -111,7 +109,6 @@ private: /* Member Functions */ static bool is_valid_alt(double alt); - static const char* get_option_val(const char* option, const char* def); void init_date_and_time_format(); void convert_datum(const Waypoint* wpt, double* dest_lat, double* dest_lon) const; void enum_waypt_cb(const Waypoint* wpt); @@ -172,23 +169,23 @@ private: std::array>, unknown_header> header_mapping_info; QStringList header_column_names; - OptionCString opt_datum; - OptionCString opt_dist; - OptionCString opt_temp; - OptionCString opt_date_format; - OptionCString opt_time_format; - OptionCString opt_precision; - OptionCString opt_utc; - OptionCString opt_grid; + OptionString opt_datum; + OptionString opt_dist; + OptionString opt_temp; + OptionString opt_date_format; + OptionString opt_time_format; + OptionInt opt_precision; + OptionInt opt_utc; + OptionString opt_grid; QVector garmin_txt_args = { - {"date", &opt_date_format, "Read/Write date format (i.e. yyyy/mm/dd)", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, + {"date", &opt_date_format, "Read/Write date format (i.e. yyyy/mm/dd)", "dd/mm/yyyy", ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, {"datum", &opt_datum, "GPS datum (def. WGS 84)", "WGS 84", ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, {"dist", &opt_dist, "Distance unit [m=metric, s=statute]", "m", ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, {"grid", &opt_grid, "Write position using this grid.", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, {"prec", &opt_precision, "Precision of coordinates", "3", ARGTYPE_INT, ARG_NOMINMAX, nullptr}, {"temp", &opt_temp, "Temperature unit [c=Celsius, f=Fahrenheit]", "c", ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, - {"time", &opt_time_format, "Read/Write time format (i.e. HH:mm:ss xx)", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, + {"time", &opt_time_format, "Read/Write time format (i.e. HH:mm:ss xx)", "HH:mm:ss", ARGTYPE_STRING, ARG_NOMINMAX, nullptr}, {"utc", &opt_utc, "Write timestamps with offset x to UTC time", nullptr, ARGTYPE_INT, "-23", "+23", nullptr}, }; diff --git a/garmin_xt.cc b/garmin_xt.cc index 6f96b2b13..8e221139e 100644 --- a/garmin_xt.cc +++ b/garmin_xt.cc @@ -74,7 +74,7 @@ GarminXTFormat::format_garmin_xt_rd_st_attrs(char* p_trk_name, uint8_t* p_track_ // get the option for the processing the track name if (opt_trk_header) { - method = xstrtoi(opt_trk_header, nullptr, 10); + method = opt_trk_header.get_result(); // if method is out of range set to default if ((method < 0) || (method > 1)) { method = 0; @@ -315,7 +315,7 @@ GarminXTFormat::format_garmin_xt_proc_atrk() // get the option for the processing the track name if (opt_trk_header) { - method = xstrtoi(opt_trk_header, nullptr, 10); + method = opt_trk_header.get_result(); } if (! track) { @@ -373,7 +373,7 @@ void GarminXTFormat::read() { // Saved Tracks file - if (strcmp(opt_xt_ftype, "STRK") == 0) { + if (opt_xt_ftype.get() == "STRK") { format_garmin_xt_proc_strk(); } else { // Active Track file format_garmin_xt_proc_atrk(); diff --git a/garmin_xt.h b/garmin_xt.h index 645b9928b..5b750db3f 100644 --- a/garmin_xt.h +++ b/garmin_xt.h @@ -34,7 +34,7 @@ #include "defs.h" #include "format.h" // for Format #include "gbfile.h" // for gbfile -#include "option.h" // for OptionCString +#include "option.h" // for OptionString class GarminXTFormat : public Format @@ -94,8 +94,8 @@ private: gbfile* fin{}; route_head* track{}; - OptionCString opt_xt_ftype; - OptionCString opt_trk_header; + OptionString opt_xt_ftype; + OptionInt opt_trk_header; QVector format_garmin_xt_args = { {"ftype", &opt_xt_ftype, "Garmin Mobile XT ([ATRK]/STRK)", "ATRK", ARGTYPE_STRING | ARGTYPE_REQUIRED, ARG_NOMINMAX, nullptr}, diff --git a/gdb.cc b/gdb.cc index 3b024e063..95d4af222 100644 --- a/gdb.cc +++ b/gdb.cc @@ -36,11 +36,10 @@ #include // for fabs #include // for printf, SEEK_SET -#include // for strtol #include // for memset, strstr, strcmp #include // for next -#include "defs.h" // for Waypoint, warning, route_head, fatal, UrlLink, bounds, UrlList, unknown_alt, xfree, waypt_add_to_bounds, waypt_init_bounds, xstrtoi, route_add_wpt, route_disp_all, waypt_bounds_valid, xmalloc, gb_color, WaypointList, find_wa... +#include "defs.h" // for Waypoint, warning, route_head, fatal, UrlLink, bounds, UrlList, unknown_alt, xfree, waypt_add_to_bounds, waypt_init_bounds, route_add_wpt, route_disp_all, waypt_bounds_valid, xmalloc, gb_color, WaypointList, find_wa... #include "formspec.h" // for FormatSpecificDataList #include "garmin_fs.h" // for garmin_fs_t, garmin_ilink_t #include "garmin_tables.h" // for gt_waypt_class_map_point, gt_color_index_by_rgb, gt_color_value, gt_waypt_classes_e, gt_find_desc_from_icon_number, gt_find_icon_number_from_desc, gt_gdb_display_mode_symbol, gt_get_icao_country, gt_waypt_class_user_waypoint, GDB, gt_display_mode_symbol @@ -1635,8 +1634,8 @@ GdbFormat::wr_init(const QString& fname) fout = gbfopen_le(fname, "wb", MYNAME); ftmp = gbfopen_le(nullptr, "wb", MYNAME); - gdb_category = (gdb_opt_category) ? xstrtoi(gdb_opt_category, nullptr, 10) : 0; - gdb_ver = (gdb_opt_ver && *gdb_opt_ver) ? xstrtoi(gdb_opt_ver, nullptr, 10) : 0; + gdb_category = gdb_opt_category ? gdb_opt_category.get_result() : 0; + gdb_ver = gdb_opt_ver.get_result(); if (gdb_category) { if ((gdb_category < 1) || (gdb_category > 16)) { @@ -1646,7 +1645,7 @@ GdbFormat::wr_init(const QString& fname) } if (gdb_opt_bitcategory) { - gdb_category = strtol(gdb_opt_bitcategory, nullptr, 0); + gdb_category = gdb_opt_bitcategory.get_result(); } waypt_nameposn_out_hash.clear(); @@ -1674,9 +1673,6 @@ GdbFormat::wr_deinit() void GdbFormat::write() { - if (gdb_opt_ver) { - gdb_ver = xstrtoi(gdb_opt_ver, nullptr, 10); - } write_header(); reset_short_handle("WPT"); diff --git a/gdb.h b/gdb.h index 87920c888..a2bcb9680 100644 --- a/gdb.h +++ b/gdb.h @@ -38,7 +38,7 @@ #include "garmin_tables.h" // for gt_waypt_classes_e #include "gbfile.h" // for gbfile #include "mkshort.h" // for MakeShort -#include "option.h" // for OptionBool, OptionCString +#include "option.h" // for OptionBool, OptionString class GdbFormat : public Format @@ -162,11 +162,11 @@ private: WptNamePosnHash waypt_nameposn_out_hash; MakeShort* short_h{}; - OptionCString gdb_opt_category; - OptionCString gdb_opt_ver; + OptionInt gdb_opt_category; + OptionInt gdb_opt_ver; OptionBool gdb_opt_via; OptionBool gdb_opt_roadbook; - OptionCString gdb_opt_bitcategory; + OptionInt gdb_opt_bitcategory; OptionBool gdb_opt_drop_hidden_wpt; int waypt_flag{}; @@ -187,7 +187,7 @@ private: }, { "bitscategory", &gdb_opt_bitcategory, "Bitmap of categories", - nullptr, ARGTYPE_INT, "1", "65535", nullptr + nullptr, ARGTYPE_BASE_AUTO | ARGTYPE_INT, "1", "65535", nullptr }, { "ver", &gdb_opt_ver, diff --git a/geo.cc b/geo.cc index caf8b674a..15eab8623 100644 --- a/geo.cc +++ b/geo.cc @@ -149,7 +149,7 @@ void GeoFormat::geo_waypt_pr(const Waypoint* waypointp, QXmlStreamWriter& writer writer.writeAttribute(QStringLiteral("lon"), QString::number(waypointp->longitude, 'f')); writer.writeEndElement(); - writer.writeTextElement(QStringLiteral("type"), deficon ? deficon.get() : waypointp->icon_descr); + writer.writeTextElement(QStringLiteral("type"), deficon ? deficon : waypointp->icon_descr); if (waypointp->HasUrlLink()) { writer.writeStartElement(QStringLiteral("link")); diff --git a/geo.h b/geo.h index 785d0c4f0..8267cfc4c 100644 --- a/geo.h +++ b/geo.h @@ -27,7 +27,7 @@ #include "defs.h" #include "format.h" // for Format #include "geocache.h" // for Geocache, Geocache::container_t -#include "option.h" // for OptionBool, OptionCString +#include "option.h" // for OptionBool, OptionString class GeoFormat : public Format @@ -67,7 +67,7 @@ private: /* Data Members */ - OptionCString deficon; + OptionString deficon; QVector geo_args = { {"deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr }, diff --git a/globalsat_sport.cc b/globalsat_sport.cc index c4a731b67..6a192b6d6 100644 --- a/globalsat_sport.cc +++ b/globalsat_sport.cc @@ -268,12 +268,12 @@ GlobalsatSportFormat::rd_init(const QString& fname) printf(MYNAME " rd_init()\n"); } if (opt_dump_file) { - dumpfile = gbfopen(opt_dump_file.get(), "wb", MYNAME); + dumpfile = gbfopen(opt_dump_file, "wb", MYNAME); if (!dumpfile) { - printf(MYNAME " rd_init() creating dumpfile %s FAILED continue anyway\n", qPrintable(opt_dump_file.get())); + printf(MYNAME " rd_init() creating dumpfile %s FAILED continue anyway\n", qPrintable(opt_dump_file)); } else { if (global_opts.debug_level > 1) { - printf(MYNAME " rd_init() creating dumpfile %s for writing binary copy of serial stream\n", qPrintable(opt_dump_file.get())); + printf(MYNAME " rd_init() creating dumpfile %s for writing binary copy of serial stream\n", qPrintable(opt_dump_file)); } } } @@ -288,11 +288,11 @@ GlobalsatSportFormat::rd_init(const QString& fname) } if (opt_timezone) { - if (QTimeZone::isTimeZoneIdAvailable(opt_timezone.getba())) { - timezn = new QTimeZone(opt_timezone.getba()); + if (QTimeZone::isTimeZoneIdAvailable(opt_timezone.get().toUtf8())) { + timezn = new QTimeZone(opt_timezone.get().toUtf8()); } else { list_timezones(); - fatal(MYNAME ": Requested time zone \"%s\" not available.\n", qPrintable(opt_timezone.get())); + fatal(MYNAME ": Requested time zone \"%s\" not available.\n", qPrintable(opt_timezone)); } } else { timezn = nullptr; diff --git a/globalsat_sport.h b/globalsat_sport.h index 374a537cb..bdebca4c5 100644 --- a/globalsat_sport.h +++ b/globalsat_sport.h @@ -47,7 +47,7 @@ #include "defs.h" #include "format.h" // for Format #include "gbfile.h" // for gbfclose, gbfopen, gbfread, gbfwrite, gbfile -#include "option.h" // for OptionCString, OptionBool +#include "option.h" // for OptionString, OptionBool class GlobalsatSportFormat : public Format @@ -231,9 +231,9 @@ private: OptionBool showlist; // if true show a list instead of download tracks - OptionCString opt_dump_file; // dump raw data to this file (optional) + OptionString opt_dump_file; // dump raw data to this file (optional) OptionBool opt_input_dump_file; // if true input is from a dump-file instead of serial console - OptionCString opt_timezone; + OptionString opt_timezone; gbfile* dumpfile{nullptr}; // used for creating bin/RAW datadump files, useful for testing gbfile* in_file{nullptr}; // used for reading from bin/RAW datadump files, useful for testing QTimeZone* timezn{nullptr}; diff --git a/gpx.cc b/gpx.cc index 5bc029e49..e65f1ef74 100644 --- a/gpx.cc +++ b/gpx.cc @@ -25,7 +25,7 @@ #include // for lround #include // for sscanf #include // for uint16_t -#include // for strchr, strncpy +#include // for strchr #include // for optional #include // for as_const @@ -102,7 +102,7 @@ GpxFormat::gpx_reset_short_handle() mkshort_handle->set_whitespace_ok(false); } - mkshort_handle->set_length(xstrtoi(snlen, nullptr, 10)); + mkshort_handle->set_length(snlen.get_result()); } void @@ -985,7 +985,7 @@ GpxFormat::wr_init(const QString& fname) * available use it, otherwise use the default. */ - if (opt_gpxver != nullptr) { + if (opt_gpxver) { gpx_write_version = QVersionNumber::fromString(opt_gpxver.get()).normalized(); } else if (!gpx_highest_version_read.isNull()) { gpx_write_version = gpx_highest_version_read; @@ -1703,7 +1703,7 @@ void GpxFormat::write() { - elevation_precision = xstrtoi(opt_elevation_precision, nullptr, 10); + elevation_precision = opt_elevation_precision.get_result(); gpx_reset_short_handle(); auto gpx_waypt_pr_lambda = [this](const Waypoint* waypointp)->void { diff --git a/gpx.h b/gpx.h index 99a1567e2..2fe36b2d5 100644 --- a/gpx.h +++ b/gpx.h @@ -35,7 +35,7 @@ #include "format.h" // for Format #include "formspec.h" // for FormatSpecificData #include "mkshort.h" // for MakeShort -#include "option.h" // for OptionBool, OptionCString +#include "option.h" // for OptionBool, OptionString #include "src/core/file.h" // for File #include "src/core/xmlstreamwriter.h" // for XmlStreamWriter #include "src/core/xmltag.h" // for xml_tag @@ -258,7 +258,7 @@ private: OptionBool opt_logpoint; OptionBool opt_humminbirdext; OptionBool opt_garminext; - OptionCString opt_elevation_precision; + OptionInt opt_elevation_precision; int logpoint_ct = 0; int elevation_precision{}; @@ -266,7 +266,7 @@ private: const QVersionNumber gpx_1_0 = QVersionNumber(1,0).normalized(); const QVersionNumber gpx_1_1 = QVersionNumber(1,1).normalized(); QVersionNumber gpx_highest_version_read; - OptionCString opt_gpxver; + OptionString opt_gpxver; QVersionNumber gpx_write_version; QXmlStreamAttributes gpx_namespace_attribute; @@ -285,9 +285,9 @@ private: QString link_type; - OptionCString snlen; + OptionInt snlen; OptionBool suppresswhite; - OptionCString urlbase; + OptionString urlbase; route_head* trk_head{}; route_head* rte_head{}; const route_head* current_trk_head{}; // Output. diff --git a/gtrnctr.cc b/gtrnctr.cc index d7a5b7838..65e866adf 100644 --- a/gtrnctr.cc +++ b/gtrnctr.cc @@ -79,7 +79,7 @@ GtrnctrFormat::wr_init(const QString& fname) if (opt_sport) { for (unsigned int i = 0; i < std::size(gtc_sportlist); i++) { - if (0 == case_ignore_strncmp(opt_sport.get(), gtc_sportlist[i], 2)) { + if (0 == case_ignore_strncmp(opt_sport, gtc_sportlist[i], 2)) { gtc_sport = i; break; } diff --git a/gtrnctr.h b/gtrnctr.h index 1627f1473..9873e0229 100644 --- a/gtrnctr.h +++ b/gtrnctr.h @@ -35,7 +35,7 @@ #include "defs.h" // for arglist_t, ff_cap, route_head, Waypoint, computed_trkdata, ARG_NOMINMAX, ff_cap_read, ARGTYPE_BOOL, ARGTYPE_STRING, ff_cap_none, ff_cap_write, ff_type, ff_type_file #include "format.h" // for Format #include "gbfile.h" // for gbfile -#include "option.h" // for OptionBool, OptionCString +#include "option.h" // for OptionBool, OptionString #include "src/core/datetime.h" // for DateTime #include "xmlgeneric.h" // for cb_cdata, xg_functor_map_entry, cb_start, cb_end @@ -133,7 +133,7 @@ private: double gtc_end_lat{}; double gtc_end_long{}; - OptionCString opt_sport; + OptionString opt_sport; OptionBool opt_course; QVector gtc_args = { diff --git a/height.cc b/height.cc index c7d56414e..778424afb 100644 --- a/height.cc +++ b/height.cc @@ -83,7 +83,7 @@ void HeightFilter::correct_height(const Waypoint* wpt) auto* waypointp = const_cast(wpt); if (waypointp->altitude != unknown_alt) { - if (addopt != nullptr) { + if (addopt) { waypointp->altitude += addf; } @@ -96,7 +96,7 @@ void HeightFilter::correct_height(const Waypoint* wpt) void HeightFilter::init() { addf = 0.0; - if (addopt != nullptr) { + if (addopt) { if (parse_distance(addopt, &addf, 1.0, MYNAME) == 0) { fatal(MYNAME ": No height specified with add option."); } diff --git a/height.h b/height.h index 8b3333076..9aedb58eb 100644 --- a/height.h +++ b/height.h @@ -32,7 +32,7 @@ #include "defs.h" // for arglist_t, ARG_NOMINMAX, ARGTYPE_BEGIN_REQ, ARGTYPE_BOOL, ARGTYPE_END_REQ, ARGTYPE_FLOAT, Waypoint #include "filter.h" // for Filter -#include "option.h" // for OptionBool, OptionCString +#include "option.h" // for OptionBool, OptionString #if FILTERS_ENABLED @@ -47,7 +47,7 @@ public: void process() override; private: - OptionCString addopt; + OptionDouble addopt; OptionBool wgs84tomslopt; double addf{}; // include static constexpr data member definitions with intializers for grid as private members. @@ -56,7 +56,7 @@ private: QVector args = { { "add", &addopt, "Adds a constant value to every altitude", - nullptr, ARGTYPE_BEGIN_REQ | ARGTYPE_FLOAT, ARG_NOMINMAX, nullptr + nullptr, ARGTYPE_ALLOW_TRAILING_DATA | ARGTYPE_BEGIN_REQ | ARGTYPE_STRING, ARG_NOMINMAX, nullptr }, { "wgs84tomsl", &wgs84tomslopt, "Converts WGS84 ellipsoidal height to orthometric height (MSL)", diff --git a/html.cc b/html.cc index e9971ed26..5df1998a4 100644 --- a/html.cc +++ b/html.cc @@ -23,6 +23,8 @@ #include // for QChar #include // for QIODevice, QIODevice::WriteOnly +#include // for QRegularExpression +#include // for QRegularExpressionMatch #include // for QString, operator!= #include // for QTextStream #include // for CaseInsensitive @@ -47,6 +49,23 @@ HtmlFormat::wr_init(const QString& fname) file_out = new gpsbabel::TextStream; file_out->open(fname, QIODevice::WriteOnly, MYNAME); mkshort_handle = new MakeShort; + + static const QRegularExpression re("^(?:ddd|dmm|dms)$"); + assert(re.isValid()); + if (re.match(opt_degformat).hasMatch()) { + degformat = opt_degformat.get().at(2).toLatin1(); + } else { + fatal(MYNAME ": Unrecognized degformat %s, expected 'ddd', 'dmm' or 'dms'.\n", qPrintable(opt_degformat)); + } + + if (opt_altunits.get().startsWith('f')) { + altunits = 'f'; + } else if (opt_altunits.get().startsWith('m')) { + altunits = 'm'; + } else { + fatal(MYNAME ": Unrecognized altunits %s, expected 'f' for feet or 'm' for meters.\n", qPrintable(opt_altunits)); + } + } void @@ -85,14 +104,14 @@ HtmlFormat::html_disp(const Waypoint* wpt) const *file_out << " \n"; *file_out << "

" << sn << " - "; *file_out << QStringLiteral("%1 (%2%3 %4 %5)") - .arg(pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", true)) + .arg(pretty_deg_format(wpt->latitude, wpt->longitude, degformat, " ", true)) .arg(utmz) .arg(utmzc) .arg(utme, 6, 'f', 0) .arg(utmn, 7, 'f', 0); if (wpt->altitude != unknown_alt) { *file_out << QStringLiteral(" alt:%1") - .arg((int)((altunits[0]=='f') ? METERS_TO_FEET(wpt->altitude) : wpt->altitude)); + .arg((int)((altunits == 'f') ? METERS_TO_FEET(wpt->altitude) : wpt->altitude)); } *file_out << "
\n"; if (wpt->description != wpt->shortname) { @@ -178,7 +197,7 @@ HtmlFormat::html_disp(const Waypoint* wpt) const double lat = logpart->xml_attribute("lat").toDouble(); double lon = logpart->xml_attribute("lon").toDouble(); *file_out << "" - << pretty_deg_format(lat, lon, degformat[2], " ", true) << "
\n"; + << pretty_deg_format(lat, lon, degformat, " ", true) << "
\n"; } logpart = curlog->xml_findfirst(u"groundspeak:text"); @@ -232,9 +251,9 @@ HtmlFormat::write() << gpsbabel_version << "\">\n"; } *file_out << " GPSBabel HTML Output\n"; - if (stylesheet) { + if (opt_stylesheet) { *file_out << R"( \n"; + << opt_stylesheet.get() << "\">\n"; } else { *file_out << "